/* 
 * File:   Terreno.cpp
 * Author: cesar
 * 
 * Implementacion de la clase Terreno.hpp y los metodos de este.
 */

#include "Terreno.hpp"

/**
 * Este metodo es el constructor de la Clase Terreno.
 * 
 * @param nombre_tex : Nombre de la textura a utilizar en el suelo.
 * @param inicio : Coordenada de inicio en Z de el plano de terreno.
 * @param final : Coordenada final en Z de el plano de terreno.
 * @param ancho : Ancho del suelo.
 */
Terreno::Terreno(char * nombre_tex, GLfloat inicio, GLfloat final, GLfloat ancho) : ObjetoGrafico(0.0, 0.0, 0.0) {
    int n = 0;
    image = NULL;
    nombre_textura = nombre_tex;
    
    //crear planos del terreno con las dimensiones especificadas.
    while (n < MAX_REC) {
        if (n == 0) {
            Rectangulos[n][INICIO] = inicio;
            Rectangulos[n][FINAL] = final;
        } else {

            Rectangulos[n][INICIO] = Rectangulos[n - 1][FINAL];
            Rectangulos[n][FINAL] = Rectangulos[n - 1][FINAL] + final;

        }


        Rectangulos[n][ANCHO_I] = ancho / 2;
        Rectangulos[n][ANCHO_D] = -ancho / 2;
        

        n++;
    }

    tope = 0;
    offset = final - inicio;

    //reflexion ambiental del material
    material_ambient[0] = 0.0;
    material_ambient[1] = 0.0;
    material_ambient[2] = 0.0;

    //reflexion difusa del material
    material_difuso[0] = 0.8;
    material_difuso[1] = 0.9;
    material_difuso[2] = 1.0;


    //reflexion especular del material
    material_especular[0] = 0.7;
    material_especular[1] = 0.7;
    material_especular[2] = 0.7;

    //emision de luz del material
    material_emision[0] = 0.8;
    material_emision[1] = 0.8;
    material_emision[2] = 0.8;

    //brillo
    material_brillo[0] = 128.0;

    //cargar texturas
    glGenTextures(1, &textura);
    glBindTexture(GL_TEXTURE_2D, textura);

       
    image = glmReadPPM(nombre_textura, &iwidth, &iheight);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iwidth, iheight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

}

/**
 * Metodo que permite hacer los calculos del desplazamiento del Terreno
 * para dar la impresion de movimiento.
 * 
 * @param s : El frameskip actual.
 */
void Terreno::idle(int s) {

    for (int i = 0; i < MAX_REC; i++) {

        Rectangulos[i][INICIO] += s;
        Rectangulos[i][FINAL] += s;

    }


    if (Rectangulos[tope][FINAL] >= 30) {
        int anterior = tope;
        tope = (tope + 1) % 3;
        int ultimo = (tope + 1) % 3;

        Rectangulos[anterior][INICIO] = Rectangulos[ultimo][FINAL];
        Rectangulos[anterior][FINAL] = Rectangulos[anterior][INICIO] + offset;


    }



}

/**
 * Este metodo permite dibujar las placas de terreno en la escena.
 */
void Terreno::dibujar() {


    
    glPushMatrix();
    
    
    glEnable(GL_TEXTURE_2D);
    
    //configurar textura
    glBindTexture(GL_TEXTURE_2D, textura);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iwidth, iheight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    
    //activar stencil test para mejrar aspecto de las sombras sobre el suelo
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_ALWAYS, 1, ~0);
    glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_difuso);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_especular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material_emision);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material_brillo);
    
    //dibujar cada placa de terreno
    for (int i = 0; i < MAX_REC; i++) {

        glBegin(GL_QUADS);
        glNormal3f(0.0, 1.0, 0.0);
        
           
             glTexCoord2f(0.0, 0.0);
            glVertex3f(Rectangulos[i][ANCHO_D], SUELO, Rectangulos[i][FINAL]);
            
            glTexCoord2f(0.0, 20.0);
            
            glVertex3f(Rectangulos[i][ANCHO_D], SUELO, Rectangulos[i][INICIO]);
            glTexCoord2f(10.0, 20.0);
       
            glVertex3f(Rectangulos[i][ANCHO_I], SUELO, Rectangulos[i][INICIO]);
            glTexCoord2f(20.0, 0.0);
            
            glVertex3f(Rectangulos[i][ANCHO_I], SUELO, Rectangulos[i][FINAL]);

            

        glEnd();
    }
    
    glDisable(GL_STENCIL_TEST);
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();
    
    
    

}

